/* ###################################################################
**     Filename    : main.c
**     Processor   : S32K1xx
**     Abstract    :
**         Main module.
**         This module contains user's application code.
**     Settings    :
**     Contents    :
**         No public methods
**
** ###################################################################*/
/*!
** @file main.c
** @version 01.00
** @brief
**         Main module.
**         This module contains user's application code.
*/         
/*!
**  @addtogroup main_module main module documentation
**  @{
*/         
/* MODULE main */

/**

RGB_BLUE        PTD16
RGB_GREEN       PTB4
RGB_RED         PTB5

LIN0_RX         PTC2
LIN0_TX         PTC3
LIN0_SLP        PTC5

*/

/* Including necessary module. Cpu.h contains other modules needed for compiling.*/
#include "Cpu.h"
#include "UDS_process.h"
#include "timer_hal.h"
#include "key.h"
#include "pwm.h"
#include "lin_ldf.h"

#include "user_config.h"
#ifdef EN_CAN_TP
    #include "bl_can.h"
#elif (defined EN_LIN_TP)
    #include "bl_lin.h"
#else
#error "Please enable CAN/LIN TP"
#endif

#define RGB_BLUE_PORT_CLK       CLK_PORTD 
#define RGB_BLUE_PORT           SYSCTRL_PORTD
#define RGB_BLUE_PIN            PTD16

#define RGB_GREEN_PORT_CLK      CLK_PORTB
#define RGB_GREEN_PORT          SYSCTRL_PORTB
#define RGB_GREEN_PIN           PTB4

#define RGB_RED_PORT_CLK        CLK_PORTB
#define RGB_RED_PORT            SYSCTRL_PORTB
#define RGB_RED_PIN             PTB5

#define RT6_PWM_HZ  (200u)

volatile int exit_code = 0;

#define POUT1_GPIO PORT_A
#define POUT1_PIN GPIO_3
#define POUT2_GPIO PORT_A
#define POUT2_PIN GPIO_7
#define POUT3_GPIO PORT_C
#define POUT3_PIN GPIO_8
#define POUT4_GPIO PORT_C
#define POUT4_PIN GPIO_9
#define POUT5_GPIO PORT_B
#define POUT5_PIN GPIO_0
#define POUT6_GPIO PORT_A
#define POUT6_PIN GPIO_1
#define POUT1_ENABLE    GPIO_SetPinOutput(POUT1_GPIO, POUT1_PIN)
#define POUT1_DISABLE   GPIO_ClearPinOutput(POUT1_GPIO, POUT1_PIN)
#define POUT2_ENABLE    GPIO_SetPinOutput(POUT2_GPIO, POUT2_PIN)
#define POUT2_DISABLE   GPIO_ClearPinOutput(POUT2_GPIO, POUT2_PIN)
#define POUT3_ENABLE    GPIO_SetPinOutput(POUT3_GPIO, POUT3_PIN)
#define POUT3_DISABLE   GPIO_ClearPinOutput(POUT3_GPIO, POUT3_PIN)
#define POUT4_ENABLE    GPIO_SetPinOutput(POUT4_GPIO, POUT4_PIN)
#define POUT4_DISABLE   GPIO_ClearPinOutput(POUT4_GPIO, POUT4_PIN)
#define POUT5_ENABLE    GPIO_SetPinOutput(POUT5_GPIO, POUT5_PIN)
#define POUT5_DISABLE   GPIO_ClearPinOutput(POUT5_GPIO, POUT5_PIN)
#define POUT6_ENABLE    GPIO_SetPinOutput(POUT6_GPIO, POUT6_PIN)
#define POUT6_DISABLE   GPIO_ClearPinOutput(POUT6_GPIO, POUT6_PIN)
#define POUT4_XOR       GPIO_TogglePinOutput(POUT4_GPIO, POUT4_PIN)
#define POUT1_XOR       GPIO_TogglePinOutput(POUT1_GPIO, POUT1_PIN)

#define PL_ENABLE POUT1_ENABLE
#define PL_DISABLE POUT1_DISABLE
#define PL_XOR POUT1_XOR
#define IS_PL_EN        GPIO_ReadPinLevel(POUT1_GPIO, POUT1_PIN)
#define SL_ENABLE POUT2_ENABLE
#define SL_DISABLE POUT2_DISABLE
#define RL_ENABLE POUT3_ENABLE
#define RL_DISABLE POUT3_DISABLE
#define TL_ENABLE POUT4_ENABLE
#define TL_DISABLE POUT4_DISABLE
#define TL_XOR POUT4_XOR
#define TL_RUN_ENABLE POUT5_ENABLE;POUT6_ENABLE
#define TL_RUN_DISABLE POUT5_DISABLE;POUT6_DISABLE

void RunTasks(void)
{
    static uint16_t keyScanTaskCnt = 0u;
    static uint16_t PWMTaskCnt = 0u;
    static uint8_t u8PwmXor = 0;

    static uint8_t PWMTaskEn = 0u;
    static uint8_t PWMDuty = 0;

    if (TRUE == TIMER_HAL_Is1msTickTimeout())
    {
        keyScanTaskCnt++;
        PWMTaskCnt++;
    }
    if (keyScanTaskCnt >= 20u)
    {
        keyScanTaskCnt = 0u;
        ToggleDebugIO();
        WATCHDOG_HAL_Fed();
        KEY_Scan();

        for (uint8_t i = 0; i < KEY_MAX; i++)
        {
            switch (key[i].event)
            {
            case TRI_EVENT:
                key[i].event = FREE_EVENT;
                break;
            case SHORT_EVENT:
                key[i].event = FREE_EVENT;
                switch (i)
                {
                case 0:
                    PL_ENABLE;
                    SetPWM(RT6_PWM_HZ, 100);
                    break;
                case 1:
                    PWMTaskCnt = 2900;
                    PWMTaskEn = 1;
                    PWMDuty = 20;
                    u8PwmXor = 1;
                    SetPWM(RT6_PWM_HZ, PWMDuty);
                    break;
                default:
                    break;
                }
                break;
            case LONG_EVENT:
                key[i].event = FREE_EVENT;
                break;
            case LOOSE_EVENT:
                key[i].event = FREE_EVENT;
                switch (i)
                {
                case 0:
                    PL_DISABLE;
                    break;
                case 1:
                    PWMTaskEn = 0;
                    SetPWM(RT6_PWM_HZ, 100);
                    break;
                default:
                    break;
                }
                break;
            default:
                key[i].event = FREE_EVENT;
                break;
            }
        }
    }
    if(PWMTaskEn && PWMTaskCnt >= 3000)
    {
        PWMTaskCnt = 0;
        switch (PWMDuty)
        {
        case 20:
            if(u8PwmXor)
            {
                u8PwmXor = 0;
                SetPWM(RT6_PWM_HZ, 100);
                PWMDuty = 40;
            }
            else
            {
                SetPWM(RT6_PWM_HZ, PWMDuty);
                u8PwmXor = 1;   
                PWMTaskCnt = 2900;            
            }
            break;
        case 40:
            if(u8PwmXor)
            {
                u8PwmXor = 0;
                SetPWM(RT6_PWM_HZ, 100);
                PWMDuty = 60;
            }
            else
            {
                SetPWM(RT6_PWM_HZ, PWMDuty);
                u8PwmXor = 1;  
                PWMTaskCnt = 2900;                
            }
            break;
        case 60:
            if(u8PwmXor)
            {
                u8PwmXor = 0;
                SetPWM(RT6_PWM_HZ, 100);
                PWMDuty = 80;
            }
            else
            {
                SetPWM(RT6_PWM_HZ, PWMDuty);
                u8PwmXor = 1;  
                PWMTaskCnt = 2900;                
            }
            break;
        case 80:
            if(u8PwmXor)
            {
                u8PwmXor = 0;
                SetPWM(RT6_PWM_HZ, 100);
                PWMDuty = 20;
            }
            else
            {
                SetPWM(RT6_PWM_HZ, PWMDuty);
                u8PwmXor = 1;   
                PWMTaskCnt = 2900;               
            }
            break;      
        default:
            break;
        }
    }
}

void POUT_Init(void)
{    
    /* enable PORTB module*/
    CLK_ModuleSrc(CLK_PORTA, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTA);
    CLK_ModuleSrc(CLK_PORTB, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTB);
    CLK_ModuleSrc(CLK_PORTC, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTC);
    CLK_ModuleSrc(CLK_PORTE, CLK_SRC_OSC40M);
    SYSCTRL_EnableModule(SYSCTRL_PORTE);

    /* enable GPIO module*/
    SYSCTRL_EnableModule(SYSCTRL_GPIO);
    
    /* set pin as GPIO*/
    PORT_PinmuxConfig(POUT1_GPIO, POUT1_PIN, PTA3_GPIO);
    PORT_PinmuxConfig(POUT2_GPIO, POUT2_PIN, PTA7_GPIO);
    PORT_PinmuxConfig(POUT3_GPIO, POUT3_PIN, PTC8_GPIO);
    PORT_PinmuxConfig(POUT4_GPIO, POUT4_PIN, PTC9_GPIO);
    PORT_PinmuxConfig(POUT5_GPIO, POUT5_PIN, PTB0_GPIO);
    PORT_PinmuxConfig(POUT6_GPIO, POUT6_PIN, PTA1_GPIO);
    PORT_PinmuxConfig(PORT_E, GPIO_9, PTE9_GPIO);  

    GPIO_SetPinDir(POUT1_GPIO, POUT1_PIN, GPIO_OUTPUT); 
    GPIO_SetPinDir(POUT2_GPIO, POUT2_PIN, GPIO_OUTPUT); 
    GPIO_SetPinDir(POUT3_GPIO, POUT3_PIN, GPIO_OUTPUT); 
    GPIO_SetPinDir(POUT4_GPIO, POUT4_PIN, GPIO_OUTPUT); 
    GPIO_SetPinDir(POUT5_GPIO, POUT5_PIN, GPIO_OUTPUT); 
    GPIO_SetPinDir(POUT6_GPIO, POUT6_PIN, GPIO_OUTPUT); 
    GPIO_SetPinDir(PORT_E, GPIO_9, GPIO_OUTPUT);

    POUT1_DISABLE;
    POUT2_DISABLE;
    POUT3_DISABLE;
    POUT4_DISABLE;
    POUT5_DISABLE;
    POUT6_DISABLE; 
}

void BSP_Init(void)
{
	 /* disable wdog */ 
    WDOG_Disable();
    
    /* enable osc clock */
    CLK_OSC40MEnable2(CLK_OSC_FREQ_MODE_HIGH, ENABLE, CLK_OSC_XTAL);
    /* choose osc clock as system clock*/
    while (ERR == CLK_SysClkSrc(CLK_SYS_OSC40M));
    /* set divide ratio of core's function clock*/
    CLK_SetClkDivider(CLK_CORE, CLK_DIV_1);
    /* set divide ratio of bus's function clock*/
    CLK_SetClkDivider(CLK_BUS, CLK_DIV_1);
    CLK_SetClkDivider(CLK_SLOW, CLK_DIV_4);
    
    KEY_Init();
    POUT_Init();
    PWM_Init();
    lin_master_Init();
    
#ifdef EN_CAN_TP
    CanInit();
#elif (defined EN_LIN_TP)
    LinInit();
#else
#error "Please enable CAN/LIN TP"
#endif
}
// 获取uds发送报文并发送
void UDS_SendMessage(void)
{
    CAN_MsgBuf_t canMessage;
    uint32 msgId;
    uint32 msgLength;
    if(TRUE == UDS_IsDataNeedTx())
    {
        if(TRUE == UDS_GetTxMsgInfo(&msgId, &msgLength, canMessage.data))
        {
            //g_bIsNeedTxMsg = TRUE;

            canMessage.cs = 0u;
            canMessage.msgId = msgId;
            canMessage.dataLen = msgLength;
            #ifdef EN_CAN_TP
            CanSendMsg(canMessage.msgId , canMessage.data);
            #elif (defined EN_LIN_TP)
            LinWriteTxQueue((void*)canMessage.data,canMessage.dataLen);
            #else
            #error "Please enable CAN/LIN TP"
            #endif            
        }
    }
}
#include "timer_hal.h"
/*! 
  \brief The main function for the project.
  \details The startup initialization sequence is the following:
 * - startup asm routine
 * - main()
*/
int main(void)
{
    /* Write your local variable definition here */

    /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
    #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
    #endif
    /*** End of Processor Expert internal initialization.                    ***/

//TIMER_HAL_Init();
    BSP_Init();
    UDS_Process_init();
#if (defined(DEV_Z20K118M))
    RGB_LED_Init();
    APPDebugPrintf("Welcome enter S32K118 CAN APP demo!\n");
#elif (defined(DEV_Z20K116M))
#else
    #error "No valid device defined!"
#endif
    
    for(;;)
    {
        //UDS_ProcessMain();
        UDS_SendMessage();   
        CanfdProcess();
        RunTasks();
    }

    /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
    /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
    #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
    #endif
    /*** End of RTOS startup code.  ***/
    /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
    for(;;) {
        if(exit_code != 0) {
          break;
        }
    }
    return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END main */
/*!
** @}
*/
/*
** ###################################################################
**
**     This file was created by Processor Expert 10.1 [05.21]
**     for the NXP S32K series of microcontrollers.
**
** ###################################################################
*/
